package acm.pta;

import java.util.*;

public class Test {
    static final int maxn = 1000007;
    static final int inf = 0x3f3f3f3f;
    static int n, m, k, ds;
    static int[][] g = new int[1100][1100];
    static Node[] a = new Node[12];
    static int idx;
    static int[] dis = new int[maxn]; // 记录当前点到起点的距离
    static boolean[] st = new boolean[maxn]; // 若当前点的最短距离已经确定 为true

    static class Node {
        int id, minn;
        double ave;
    }

    static void dfs(int s) {
        Arrays.fill(dis, inf); // 初始化距离为正无穷
        Arrays.fill(st, false);
        dis[s] = 0; // 从1开始更新
        for (int i = 0; i < n + m - 1; i++) {
            int t = -1;
            // 找到当前不在st中而且距离最小的点t
            for (int j = 1; j <= n + m; j++)
                if (!st[j] && (t == -1 || dis[t] > dis[j]))
                    t = j;
            // 用点t更新其他不在st中的点的距离
            for (int j = 1; j <= n + m; j++)
                dis[j] = Math.min(dis[j], dis[t] + g[t][j]);
            // 将t点放到st集合里
            st[t] = true;
        }
        int res = inf, cnt = 0, sum = 0;
        for (int i = 1; i <= n; i++) {
            if (dis[i] > ds) {
                break;
            }
            sum += dis[i];
            cnt++;
            res = Math.min(res, dis[i]);
        }
        if (cnt == n) {
            idx++;
            a[idx] = new Node();
            a[idx].id = s;
            a[idx].minn = res;
            a[idx].ave = sum * 1.0 / n;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        k = sc.nextInt();
        ds = sc.nextInt();
        for (int i = 1; i <= n + m; i++)
            for (int j = 1; j <= n + m; j++)
                if (i == j) g[i][j] = 0;
                else g[i][j] = inf;
        for (int i = 1; i <= k; i++) {
            String x = sc.next();
            String y = sc.next();
            int t = sc.nextInt();
            int cntx = 0, cnty = 0;
            if (x.charAt(0) == 'G') {
                for (int j = 1; j < x.length(); j++)
                    cntx = cntx * 10 + x.charAt(j) - '0';
                cntx += n;
            } else {
                for (int j = 0; j < x.length(); j++)
                    cntx = cntx * 10 + x.charAt(j) - '0';
            }
            if (y.charAt(0) == 'G') {
                for (int j = 1; j < y.length(); j++)
                    cnty = cnty * 10 + y.charAt(j) - '0';
                cnty += n;
            } else {
                for (int j = 0; j < y.length(); j++)
                    cnty = cnty * 10 + y.charAt(j) - '0';
            }
            g[cntx][cnty] = g[cnty][cntx] = Math.min(t, g[cntx][cnty]);
        }
        for (int i = n + 1; i <= n + m; i++)
            dfs(i);
        if (idx == 0) System.out.println("No Solution");
        else {
            Arrays.sort(a, 1, idx + 1, new Comparator<Node>() {
                public int compare(Node a, Node b) {
                    if (a.minn == b.minn) {
                        if (a.ave == b.ave) {
                            return a.id - b.id;
                        }
                        return Double.compare(a.ave, b.ave);
                    }
                    return b.minn - a.minn;
                }
            });
            System.out.println("G" + (a[1].id - n));
            System.out.printf("%.1f %.1f\n", 1.0 * a[1].minn, a[1].ave);
        }
    }
}
